/**
 *
 */
package cre.gutwo.convert;

import cre.gutwo.domain.CompanyCode;
import cre.gutwo.domain.DataModel;
import cre.gutwo.domain.DeviceInfo;
import cre.gutwo.service.RuleService;
import cre.gutwo.util.Constants;
import cre.gutwo.util.FrameUtil;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Cre.Gu
 */
public abstract class DefaultConverter implements Converter {

    @Resource
    protected RuleService ruleService;

    protected Map<String, String> diNotFounds = new HashMap<String, String>();
    protected Map<String, String> diSames = new HashMap<String, String>();

    @Override
    public List<DataModel> convert(List<DataModel> orgiDatas, String type) throws Exception {
        List<DataModel> results = new ArrayList<DataModel>();

        try {
            diNotFounds.clear();
            diSames.clear();

            FrameUtil.println("总共数据有：" + orgiDatas.size() + "条。");
            int i = 0;

            for (Iterator<DataModel> iterator = orgiDatas.iterator(); iterator.hasNext(); ) {
                int j = (++i);
                FrameUtil.println("正在转换第" + j + "条。");

                DataModel dm = iterator.next();
                DataModel re = new DataModel();

                doConvert(re, dm);
                doCheck(re, dm, j + 1);

                results.add(re);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("转换错误");
        }

        return results;
    }

    @Override
    public void findSames(List<DataModel> destDatas) throws Exception {
        for (Map.Entry<String, String> key : diSames.entrySet()) {
            String val = key.getValue();

            if (StringUtils.contains(val, ",")) {
                FrameUtil.println("deviceId重复：" + key.getKey() + "，行号：" + val);
            }
        }

        for (Map.Entry<String, String> key : diNotFounds.entrySet()) {
            FrameUtil.println("device未匹配：" + key.getKey() + "，行号：" + key.getValue());
        }

    }

    /**
     * 做检查，找不到对应的DeviceInfo和DeviceId相同的行号
     *
     * @param re
     * @param dm
     * @param j
     */
    protected void doCheck(DataModel re, DataModel dm, int j) {
        if (!re.isDeviceInfoFound()) {
            String dn = re.get(Constants.DEVICENAME);
            if (StringUtils.isBlank(dn)) {
                dn = re.get(Constants.PCName);
            }

            diNotFounds.put(dn, String.valueOf(j));
        }

        String deviceId = re.get(Constants.DEVICE_ID);
        if (StringUtils.isBlank(deviceId)) {
            deviceId = re.get(Constants.PCID);
        }

        if (StringUtils.isBlank(deviceId)) {
            return;
        }

        if (diSames.containsKey(deviceId)) {
            String val = diSames.get(deviceId);

            val = (val + "," + j);
            diSames.put(deviceId, val);
        } else {
            diSames.put(deviceId, String.valueOf(j));
        }
    }

    protected void doConvert(DataModel re, DataModel dm) {
        // 目标数据，加头部
        putDestHeaders(re);

        // 将源数据的列覆盖到目标数据
        re.putAll(dm.getModel());

		/*
         * 将特殊列做转换
		 */
        specConvert(dm, re);
    }

    /**
     * 目标数据，加头部
     *
     * @param re void
     * @author Cre.Gu at 2015年12月13日
     */
    protected abstract void putDestHeaders(DataModel re);

    /**
     * 将特殊列做转换
     *
     * @param dm
     * @param re void
     * @author Cre.Gu at 2015年12月13日
     */
    protected abstract void specConvert(DataModel dm, DataModel re);

    protected DeviceInfo gainDeviceInfo(DataModel dm) {
        // dis = ruleService.findDis();
        String deviceName = gainDeviceName(dm);

        if (StringUtils.isBlank(deviceName))
            return null;

        // for (DeviceInfo di : dis) {
        // if (deviceName.equals(di.getDeviceName()))
        // return di;
        // }
        return ruleService.findByDeviceName(deviceName);
    }

    protected CompanyCode gainCompanyCode(DataModel re) {
        // ccs = ruleService.findCcs();
        String cname = re.get(Constants.DEVICENAME);

        if (StringUtils.isBlank(cname))
            return null;

        // for (CompanyCode cc : ccs) {
        // if (cname.equals(cc.getName()))
        // return cc;
        // }

        DeviceInfo di = ruleService.findByDeviceName(cname);
        if (di != null && di.getLinkageID() != null) {
            return ruleService.findCcByName(di.getLinkageID());
        }
        return null;
    }

    protected String gainDeviceName(DataModel dm) {
        return dm.get(Constants.DEVICENAME);
    }

    protected void changeValDi(DataModel re, DeviceInfo di, String spec) {
        if (re.containsKey(spec)) {
            re.put(spec, changeValDiInternal(di, spec));
        }
    }

    protected String changeValDiInternal(DeviceInfo di, String spec) {
        if (Constants.LINKAGE_ID.equals(spec)) {
            return "AP";
        } else if (Constants.MACADDR.equals(spec)) {
            return di.getMacAddr();
        } else if (Constants.IPADDR.equals(spec)) {
            return di.getIpAddr();
        } else if (Constants.OS.equals(spec)) {
            return di.getOs();
        } else if (Constants.OS_LEVEL.equals(spec)) {
            return di.getOsLevel();
        } else if (Constants.DEVICE_ID.equals(spec) || Constants.PCID.equals(spec)) {
            return "AP" + "-" + di.getUniqueKey();
        }
        return "";
    }

    protected void changeValCc(DataModel re, CompanyCode cc, String spec) {
        if (re.containsKey(spec)) {
            String val = "";
            if (Constants.COMPANYID.equals(spec)) {
                val = cc.getCode();
            }

            re.put(spec, val);
        }
    }

    protected Map<String, String> gainHwDestHeaders() {
        Map<String, String> headers = new LinkedHashMap<String, String>();

        headers.put("DEVICE_ID", "");
        headers.put("DEVICENAME", "");
        headers.put("ORGANIZATION", "");
        headers.put("PERSON", "");
        headers.put("OS", "");
        headers.put("OS_LEVEL", "");
        headers.put("CPU", "");
        headers.put("CPU_SPEED", "");
        headers.put("BIOS", "");
        headers.put("KEYBOARD", "");
        headers.put("MOUSE", "");
        headers.put("VIDEO", "");
        headers.put("MEMORY", "");
        headers.put("LANGUAGE", "");
        headers.put("IPADDR", "");
        headers.put("SUBNETMASK", "");
        headers.put("SUBNETADDR", "");
        headers.put("MACADDR", "");
        headers.put("N_PARALLEL", "");
        headers.put("N_SERIAL", "");
        headers.put("N_PRINTER", "");
        headers.put("SYSDRV", "");
        headers.put("SYSDRV_TOTAL", "");
        headers.put("SYSDRV_FREE", "");
        headers.put("CHASSISTYPE", "");
        headers.put("PCID", "");
        headers.put("SITECODE", "");
        headers.put("OWNERID", "");
        headers.put("REGION", "");
        headers.put("DOMAIN", "");
        headers.put("COMPANYID", "");
        headers.put("PILOT", "");
        headers.put("RESPONSIBLEIT", "");
        headers.put("WDOMAIN", "");
        headers.put("WMANUFACTURER", "");
        headers.put("WMODEL", "");
        headers.put("WNUMBEROFPROCESSORS", "");
        headers.put("WSYSTEMTYPE", "");
        headers.put("WVIDEOMODEDESCRIPTION", "");
        headers.put("SERIAL_NUMBER", "");
        headers.put("DESKTOP_OR_LAPTOP", "");
        headers.put("WDNSHOSTNAME", "");
        headers.put("WDNSDOMAIN", "");
        headers.put("WDNSDOMAINSUFFIXSEARCHORDER", "");
        headers.put("HWARCHITECTURE", "");
        headers.put("SWADDRESSWIDTH", "");
        headers.put("LASTCONNECTDATE", "");
        headers.put("Linkage ID", "");
        return headers;
    }

    protected Map<String, String> gainSwDestHeaders() {
        Map<String, String> headers = new LinkedHashMap<String, String>();

        headers.put("Company", "");
        headers.put("PC Sitecode", "");
        headers.put("User Login Name", "");
        headers.put("PCID", "");
        headers.put("PC Name", "");
        headers.put("Software Name", "");
        headers.put("Software Version", "");
        headers.put("Software Path", "");
        headers.put("Software Vendor", "");
        headers.put("Scan Date", "");
        headers.put("Linkage ID", "");
        return headers;
    }
}
